import { UserDao } from "../account_server/dao/UserDao"
import { UserResourceDao } from "../account_server/dao/UserResourceDao"
import { UserEntity } from "../account_server/entity/UserEntity"
import { AccountModel } from "../account_server/model/AccountModel"
import { UserModel } from "../account_server/model/UserModel"

import { ChannelConfig } from "../src/config/ChannelConfig"
import { ErrorCode } from "../src/config/ErrorCode"
import { GameConfig } from "../src/config/GameConfig"
import { RoomConfig } from "../src/config/RoomConfig"
import RoomConfig_Mj from "../src/config/RoomConfig_Mj"
import { ServerConfig } from "../src/config/ServerConfig"
import { SocketClientReqManager } from "../src/engine/socketclient/SocketClientReqManager"
import { SocketConnection } from "../src/engine/socketserver/socket/SocketConnection"
import { SocketConnectionManager } from "../src/engine/socketserver/socket/SocketConnectionManager"
import { SocketMsg } from "../src/engine/socketserver/socket/SocketMsg"
import DateUtil from "../src/engine/utils/DateUtil"
import { Logger } from "../src/engine/utils/Logger"
import { JhaoProto } from "../src/lib/net/protobuf/jhaoproto"
import { ProtoManager } from "../src/lib/net/protobuf/ProtoManager"
import { ResponseModel } from "../src/model/ResponseModel"
import { RoomManager } from "../src/server/RoomManager"
import { ServerManager } from "../src/server/ServerManager"
import { WebVersionModel } from "../web_server/model/WebVersionModel"
import { Club_SocketMsgHandler } from "./Club_SocketMsgHandler"
import { ClubDao } from "./dao/ClubDao"
import { UserRoomDao } from "./dao/UserRoomDao"
import { RoomEntity } from "./entity/RoomEntity"
import { UserRoomEntity } from "./entity/UserRoomEntity"
import { RoomModel } from "./model/RoomModel"
import { RoomPlayer } from "./model/RoomPlayer"

export class HallServer_SocketMsgHandler {


    public static onEventSocketGata(socketConnect: SocketConnection, msg: JhaoProto.BaseMsg) {
        // Logger.log("HallServer_SocketMsgHandler=", msg)
        if (this.checkServer(socketConnect)) {
            try {
                if (msg.cmdIndex == JhaoProto.CmdIndex.Login) {
                    this.onReqLogin(socketConnect, msg)
                }
                else {
                    if (socketConnect.isLogin()) {
                        if (msg.cmdIndex == JhaoProto.CmdIndex.Ping) {
                            this.onReqPing(socketConnect, msg)
                        }
                        else if (msg.cmdIndex == JhaoProto.CmdIndex.create_room) {
                            this.create_room(socketConnect, msg)
                        }
                        else {
                            Club_SocketMsgHandler.onEventSocketGata(socketConnect, msg)
                        }
                    } else {
                        socketConnect.sendErrorToClient(0, JhaoProto.ErrorCodeWs.LoginError_NoLogin, "账号未登录")
                    }
                }
            } catch (error) {
                Logger.warn("allServer_SocketMsgHand error==", error, socketConnect.account, socketConnect.user, socketConnect.ip, socketConnect.id, msg)
            }
        }
    }

    public static checkWeihu(socketConnect: SocketConnection) {
        if (ServerConfig.nowServerConfig.status == ServerConfig.Status_Type.Weihu) {
            socketConnect.sendErrorToClient(0, JhaoProto.ErrorCodeWs.Server_Weihu, ErrorCode.code2Msg.get(ErrorCode.Code.Server_Weihu))
            return true
        }
    }

    public static checkServer(socketConnect: SocketConnection) {
        if (ServerConfig.nowServerConfig.status == ServerConfig.Status_Type.Normal) {
            return true
        }
        else if (ServerConfig.nowServerConfig.status == ServerConfig.Status_Type.Weihu) {
            return true
        }
    }

    private static async onReqLogin(new_conn: SocketConnection, socketMsg: JhaoProto.BaseMsg) {
        Logger.log("on_req_login====", socketMsg)
        let loginProto: JhaoProto.IReqLogin = ProtoManager.instance.decode(JhaoProto.ReqLogin, socketMsg.data)
        let respModel: ResponseModel = await AccountModel.login_async(loginProto.account, loginProto.token)
        if (respModel.code == ErrorCode.Code.Suc) {
            let old_conn_list: Array<SocketConnection> = SocketConnectionManager.instance.getSocketConnectionByUser(loginProto.account);
            for (let i = 0; i < old_conn_list.length; i++) {
                let old_conn: SocketConnection = old_conn_list[i]
                if (old_conn && old_conn.id != new_conn.id) {
                    old_conn.sendErrorToClient(0, JhaoProto.ErrorCodeWs.LoginError_MultiLogin, "异地登录");
                    old_conn.gotoClose();
                }
            }
            new_conn.account = loginProto.account
            let userData: UserEntity = await UserDao.get_user_data_by_account(loginProto.account)
            if (userData) {
                if (userData.status != GameConfig.Status_Type.Normal) {
                    respModel.code = ErrorCode.Code.Feng_jin
                    respModel.msg = "用户被冻结，请联系客服";
                } else {
                    userData.ip = new_conn.ip
                    userData.last_login_time = DateUtil.formatDateStr(DateUtil.now())
                    userData = await UserDao.update_user(userData)
                    if (!userData) {
                        respModel.code = ErrorCode.Code.Fail
                        respModel.msg = "用户登录更新数据失败";
                    }
                }
            } else {
                userData = new UserEntity()
                userData.account = loginProto.account
                userData.nick_name = loginProto.nickname
                userData.sex = loginProto.sex
                userData.headimgurl = loginProto.headimgurl
                userData.ip = new_conn.ip
                userData.create_time = DateUtil.formatDateStr(DateUtil.now())
                userData.last_login_time = userData.create_time
                userData = await UserDao.update_user(userData)
                if (!userData) {
                    respModel.code = ErrorCode.Code.Fail
                    respModel.msg = "创建用户失败";
                }
            }
            if (respModel.code == ErrorCode.Code.Suc) {
                let user: UserModel = await UserModel.db2Model(userData)
                new_conn.user = user
                let resourceObj: object = await UserResourceDao.getResource(user.userid)
                user.resource2Model(resourceObj)
                let userRoomEntity: UserRoomEntity = await UserRoomDao.getUser(user.userid)
                user.room_id = userRoomEntity.room_id
                respModel.data = user.model2proto()
            }
        }
        if (respModel.code == ErrorCode.Code.Suc) {
            let respData: JhaoProto.IRespLogin = {
                userInfo: respModel.data
            }
            new_conn.createMsgToClient(socketMsg.cmdIndex, socketMsg.cmdOrder, JhaoProto.RespLogin, respData)
        } else {
            new_conn.sendErrorToClient(socketMsg.cmdOrder, respModel.code, respModel.msg)
        }
    }

    private static onReqPing(conn: SocketConnection, socketMsg: JhaoProto.BaseMsg) {
        let protoPack: JhaoProto.IReqPing = ProtoManager.instance.decode(JhaoProto.ReqPing, socketMsg.data)
        let needUpdate: boolean = WebVersionModel.getNeedUpate(ChannelConfig.Channel_Type.android, protoPack.version)
        let respData: JhaoProto.IRespPing = {
            t: DateUtil.now(),
            n: needUpdate
        }
        conn.createMsgToClient(socketMsg.cmdIndex, socketMsg.cmdOrder, JhaoProto.RespPing, respData)
    }

    private static async create_room(conn: SocketConnection, socketMsg: JhaoProto.BaseMsg) {
        let protoPack: JhaoProto.req_create_room = ProtoManager.instance.decode(JhaoProto.req_create_room, socketMsg.data)
        let user: UserModel = conn.user
        let serverConfig: ServerConfig = ServerConfig.randomGameServer(protoPack.gameType)
        let serverStatus: number = await SocketClientReqManager.instance.req_server_internal_get_server_status(serverConfig)
        Logger.log("create_room========1==", serverConfig)
        if (serverStatus == ServerConfig.Status_Type.Weihu) {
            conn.sendErrorToClient(socketMsg.cmdOrder, JhaoProto.ErrorCodeWs.Fail, "服务器维护")
        } else {
            let inRoomId: number = RoomModel.isInRoom(user.userid)
            if (inRoomId > 0) {
                conn.sendErrorToClient(socketMsg.cmdOrder, JhaoProto.ErrorCodeWs.Fail, "您已经在其他房间了哦:" + inRoomId)
            } else {
                if (protoPack.gameType == GameConfig.Game_Type.Mj) {
                    let renShuIndex: number = RoomConfig_Mj.renshuConfig.indexOf(protoPack.roomConfigBase.renshu)
                    let jushuIndex: number = RoomConfig_Mj.jushuConfig.indexOf(protoPack.roomConfigBase.jushu)
                    protoPack.roomConfigBase.cost = RoomConfig_Mj.fangfeiConfig[renShuIndex][jushuIndex]
                }
                //平均
                if (protoPack.roomConfigBase.costType == RoomConfig.cost_type.pingjun) {
                    protoPack.roomConfigBase.cost = Math.floor(protoPack.roomConfigBase.cost / protoPack.roomConfigBase.renshu)
                }
                if (protoPack.roomConfigBase.distanceLimit > 0) { //开启了房间位置限制
                    // if (!user.location) {
                    //     respModel.code = ErrorCode.Code.Fail
                    //     respModel.msg = "创建房间失败，获取不到您位置"
                    // }
                    Logger.log("create_room========333==创建房间失败，获取不到您位置")
                    conn.sendErrorToClient(socketMsg.cmdOrder, JhaoProto.ErrorCodeWs.Fail, "创建房间失败，获取不到您位置")
                    return
                }

                if (protoPack.roomType == RoomConfig.Room_Type.Create) {
                    if (user.diamond < protoPack.roomConfigBase.cost) {
                        Logger.log("create_room========333==玩家钻石不足")
                        conn.sendErrorToClient(socketMsg.cmdOrder, JhaoProto.ErrorCodeWs.Fail, "玩家钻石不足")
                        return
                    }
                }


                let room: JhaoProto.IRoomModel = {
                    roomId: RoomModel.generateRoomId(),
                    name: "",
                    roomType: protoPack.roomType,
                    gameType: protoPack.gameType,
                    creator: user.userid,
                    roomConfigBase: protoPack.roomConfigBase,
                    roomConfigMj: protoPack.roomConfigMj,
                    clubid: 0,
                    numOfTurns: 0,
                    createTime: DateUtil.now(),
                    serverId: serverConfig.id,
                    playerList:[],
                    gameInfoBase:{},
                    gameInfoMj:{}
                }
                let player: JhaoProto.IRoomPlayer = RoomPlayer.createPlayerByUser(user, room)
                Logger.log("create_room========4444==", player)
                if (RoomModel.insertPlayer(player, room)) {
                    let entity: RoomEntity = await RoomModel.insertRoom(room);
                    if (entity) {
                        inRoomId = RoomModel.isInRoom(user.userid)
                        if (inRoomId > 0) {
                            Logger.log("create_room========666==创建房间已经在其他房间")
                            conn.sendErrorToClient(socketMsg.cmdOrder, JhaoProto.ErrorCodeWs.Fail, "创建房间已经在其他房间" + inRoomId)
                            RoomManager.instance.delete_room([room.roomId], [room], ["创建房间已经在其他房间"])
                            return
                        }
                        ServerManager.instance.createRoom(room)
                        UserRoomDao.update_user(user.userid, room.roomId)
                        let protoResp: JhaoProto.Iresp_create_room = {
                            room: room,
                        }
                        conn.createMsgToClient(socketMsg.cmdIndex, socketMsg.cmdOrder, JhaoProto.resp_create_room, protoResp)
                    } else {
                        Logger.log("create_room========7777==创建房间时数据库失败")
                        conn.sendErrorToClient(socketMsg.cmdOrder, JhaoProto.ErrorCodeWs.Fail, "创建房间时数据库失败")
                        return
                    }
                }
                else{
                    Logger.log("create_room========55555==插入玩家失败")
                }


            }
        }
    }



    public static notify_update_gems(userid: number) {
        // SocketConnectionManager.instance.socketConnMap.forEach(async (conn: SocketConnection, key: number) => {
        //     if (conn.isLogin() && conn.user) {
        //         if (conn.user.userid == userid) {
        //             let respModel: ResponseModel = new ResponseModel()
        //             conn.user.gems = await UserDao.getGems(userid);
        //             respModel.data = conn.user.gems
        //             return
        //         }
        //     }
        // });
    }

    public static notify_update_coins(userid: number) {
        SocketConnectionManager.instance.socketConnMap.forEach(async (conn: SocketConnection, key: number) => {
            if (conn.isLogin() && conn.user) {
                if (conn.user.userid == userid) {
                    let respModel: ResponseModel = new ResponseModel()
                    // conn.user.coins = await UserDao.getCoins(userid)
                    // respModel.data = conn.user.coins
                    // conn.createMsgToClient(0, ProtoConfig.notify_update_coins, respModel)
                    RoomManager.instance.checkUpdatePlayerCoin(conn.user)
                    return
                }
            }
        });
    }





}